﻿using System;
using System.IO;
using System.Windows.Media.Imaging;

namespace YsTiffConverter.DataModel
{
    /// <summary>
    /// Contains TIFF image data.
    /// </summary>
    public class TiffImage : BaseDataObject
    {
        #region Fields

        /// <summary>
        /// Holds the current frame number.
        /// </summary>
        private int currentFrameNumber_;

        /// <summary>
        /// Holds the tiff decoder.
        /// </summary>
        private TiffBitmapDecoder tiffDecoder_;

        /// <summary>
        /// Holds the image file name;
        /// </summary>
        private string fileName_;
        #endregion Fields

        #region Properties

        /// <summary>
        /// Gets the current frame number.
        /// </summary>
        public int CurrentFrameNumber
        {
            get
            {
                return currentFrameNumber_;
            }
            private set
            {
                if (tiffDecoder_ != null
                    && 0 <= value && value < tiffDecoder_.Frames.Count)
                {
                    currentFrameNumber_ = value;
                    SetPropertyChanged("CurrentFrameNumber");
                    SetPropertyChanged("CurrentFrame");
                    SetPropertyChanged("ImagePage");
                }
            }
        }

        /// <summary>
        /// Gets the image page number.
        /// </summary>
        public int ImagePage
        {
            get
            {
                return CurrentFrameNumber + 1;
            }
        }

        /// <summary>
        /// Gets the frames count.
        /// </summary>
        public int FrameCount
        {
            get
            {
                //return (tiffDecoder_ != null)? tiffDecoder_.Frames.Count : 0;
                return 6;//test
            }
        }

        /// <summary>
        /// Gets the current bitmap frame. The return value may be null.
        /// </summary>
        public BitmapFrame CurrentFrame
        {
            get
            {
                if (tiffDecoder_ != null
                    && currentFrameNumber_ < tiffDecoder_.Frames.Count)
                {
                    return tiffDecoder_.Frames[currentFrameNumber_];
                }

                return null;
            }
        }

        /// <summary>
        /// Gets or sets the file name.
        /// </summary>
        public string FileName
        {
            get
            {
                if (fileName_ == null)
                {
                    fileName_ = String.Empty;
                }
                return fileName_;
            }
            set
            {
                fileName_ = value;
                SetPropertyChanged("FileName");
            }
        }

        public BitmapFrame this[int i]
        {
            get
            {
                if (0 <= i && i < this.tiffDecoder_.Frames.Count)
                {
                    return tiffDecoder_.Frames[i];
                }

                return null;
            }
        }
        #endregion Properties

        #region Constructors

        public TiffImage()
        {
            currentFrameNumber_ = 0;
            tiffDecoder_ = null;
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Moves the next frame.
        /// </summary>
        /// <returns>True, if succeeded; otherwise - false.</returns>
        public bool NextFrame()
        {
            if (tiffDecoder_ != null
                && currentFrameNumber_ < (tiffDecoder_.Frames.Count - 1))
            {
                CurrentFrameNumber = currentFrameNumber_ + 1;
                SetPropertyChanged("CurrentFrame");
                return true;
            }

            return false;
        }

        /// <summary>
        /// Moves the previous frame.
        /// </summary>
        /// <returns>True, if succeeded; otherwise - false.</returns>
        public bool PreviousFrame()
        {
            if (tiffDecoder_ != null
                && currentFrameNumber_ > 0)
            {
                CurrentFrameNumber = currentFrameNumber_ - 1;
                SetPropertyChanged("CurrentFrame");
                return true;
            }

            return false;
        }

        /// <summary>
        /// Opens image file.
        /// </summary>
        /// <param name="fileName">Specifies the image file.</param>
        /// <param name="errorText">receives the error text or null.</param>
        /// <returns>True, if succeeded; otherwise - false.</returns>
        public bool Open(string fileName, out string errorText)
        {
            try
            {
                using (Stream imageStreamSource = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    tiffDecoder_ = new TiffBitmapDecoder(imageStreamSource,
                                                         BitmapCreateOptions.PreservePixelFormat,
                                                         BitmapCacheOption.OnLoad);
                    

                    currentFrameNumber_ = 0;
                    CurrentFrameNumber = 0;
                    FileName = fileName;
                    errorText = null;
                    return true;
                }
            }
            catch (FileNotFoundException)
            {
                errorText = "Can't open file " + fileName;
            }
            catch (FileFormatException excp)
            {
                errorText = String.Format("Can't open file {0}: {1}", fileName, excp.Message);
            }

            return false;
        }

        /// <summary>
        /// Sets the 1st frame as current frame.
        /// </summary>
        /// <returns>True, if succeeded; otherwise - false.</returns>
        public bool SetFirstFrame()
        {
            if (FrameCount > 0)
            {
                CurrentFrameNumber = 0;
                return true;
            }

            return false;
        }

        #endregion Methods

        #region Overrides

        #region BaseDataObject members

        protected override void Save()
        {
            throw new NotImplementedException();
        }

        protected override void Restore()
        {
            throw new NotImplementedException();
        }
        #endregion BaseDataObject members

        #endregion Overrides
    }
}
